<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Custom Random Layout</title>
  </head>

  <body>
    <div id="description">
      自定义布局，根据数据中节点的属性分配随机坐标， cluster 为 a、b、c、d
      的节点分别放置在左上角、右上角、左下角、右下角中
    </div>
    <div id="mountNode"></div>
    <script src="../build/g6.js"></script>
    <script>
      const data = {
        nodes: [
          {
            id: '0',
            label: '0',
            cluster: 'a',
          },
          {
            id: '1',
            label: '1',
            cluster: 'b',
          },
          {
            id: '2',
            label: '2',
            cluster: 'a',
          },
          {
            id: '3',
            label: '3',
            cluster: 'a',
          },
          {
            id: '4',
            label: '4',
            cluster: 'c',
          },
          {
            id: '5',
            label: '5',
            cluster: 'c',
          },
          {
            id: '6',
            label: '6',
            cluster: 'c',
          },
          {
            id: '7',
            label: '7',
            cluster: 'b',
          },
          {
            id: '8',
            label: '8',
            cluster: 'd',
          },
          {
            id: '9',
            label: '9',
            cluster: 'd',
          },
        ],
        edges: [
          {
            source: '0',
            target: '1',
          },
          {
            source: '0',
            target: '2',
          },
          {
            source: '0',
            target: '3',
          },
          {
            source: '0',
            target: '4',
          },
          {
            source: '0',
            target: '5',
          },
          {
            source: '0',
            target: '7',
          },
          {
            source: '0',
            target: '8',
          },
          {
            source: '0',
            target: '9',
          },
          {
            source: '2',
            target: '3',
          },
          {
            source: '4',
            target: '5',
          },
          {
            source: '4',
            target: '6',
          },
          {
            source: '5',
            target: '6',
          },
        ],
      };

      G6.registerLayout('myLayout', {
        execute() {
          const self = this;
          const nodes = self.nodes;
          const clusterRectRatio = 1 / 5;
          const padding = 50;
          nodes.forEach(node => {
            let pos = [0, 0];
            switch (node.cluster) {
              case 'a': {
                pos = randomInRange(
                  [padding, self.width * clusterRectRatio],
                  [padding, self.height * clusterRectRatio],
                );
                break;
              }
              case 'b': {
                pos = randomInRange(
                  [self.width * (1 - clusterRectRatio), self.width - padding],
                  [padding, self.height * clusterRectRatio],
                );
                break;
              }
              case 'c': {
                pos = randomInRange(
                  [padding, self.width * clusterRectRatio],
                  [self.height * (1 - clusterRectRatio), self.height - padding],
                );
                break;
              }
              case 'd': {
                pos = randomInRange(
                  [self.width * (1 - clusterRectRatio), self.width - padding],
                  [self.height * (1 - clusterRectRatio), self.height - padding],
                );
                break;
              }
            }
            node.x = pos[0];
            node.y = pos[1];
          });
        },
      });

      const graph = new G6.Graph({
        container: 'mountNode',
        width: 800,
        height: 600,
        layout: {
          type: 'myLayout',
        },
        animate: true,
        modes: {
          default: ['drag-node'],
        },
        defaultNode: {
          size: [20, 20],
          color: 'steelblue',
        },
        defaultEdge: {
          size: 1,
          color: '#e2e2e2',
          style: {
            endArrow: {
              path: 'M 4,0 L -4,-4 L -4,4 Z',
              d: 4,
            },
          },
        },
      });
      graph.data(data);
      graph.render();

      // make the graph re-layout when the cluster info changed
      setTimeout(() => {
        data.nodes[0].cluster = 'd';
        graph.layout();
      }, 2000);

      // generage random position with ranges of x and y
      function randomInRange(xRange, yRange) {
        const xScale = xRange[1] - xRange[0];
        const yScale = yRange[1] - yRange[0];
        const x = Math.random() * xScale + xRange[0];
        const y = Math.random() * yScale + yRange[0];
        return [x, y];
      }
    </script>
  </body>
</html>
